using System;
using System.Reactive.Subjects;
using System.Collections.Generic;

namespace Patterns.FeedOperators
{
    public static class SubjectExt
    {
        public static Subject<T> Where<T>(this Subject<T> subject, Predicate<T> predicate )
        {
            var result = new Subject<T>();
            subject.Subscribe((a) =>
            {
                if (predicate == null)
                    result.OnNext(a);
                else
                    if (predicate(a))
                        result.OnNext(a);
            });
            return result;
        }

        public static Subject<TOut> Select<TIn, TOut>(this Subject<TIn> subject, Func<TIn, TOut> constructor)
        {
            var result = new Subject<TOut>();
            subject.Subscribe((a) => result.OnNext(constructor(a)));
            return result;
        }

        public static Subject<T> Aggregate<T>(this Subject<T> subject, T initVal, Func<T, T, T> aggregator)
        {
            var result = new Subject<T>();
            T buffer = initVal;
            subject.Subscribe((a) =>
            {
                buffer = aggregator(buffer, a);
                result.OnNext(buffer);
            });
            return result;
        }

        public static Subject<T> Union<T>(this Subject<T> subject1, Subject<T> subject2)
        {
            var result = new Subject<T>();
            subject1.Subscribe(result.OnNext);
            subject2.Subscribe(result.OnNext);
            return result;
        }

        public static Subject<T> Browse<T>(this Subject<T> subject, IEnumerable<T> enumerable)
        {
            foreach (var element in enumerable)
                subject.OnNext(element);
            return subject;
        }

        public static List<T> Save<T>(this Subject<T> subject)
        {
            var enumerable = new List<T>();
            subject.Subscribe(enumerable.Add);
            return enumerable;
        }
    }
}